package com.todod.common.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.todod.exception.DownLoadException;

/**
 * 
 * 压缩文件
 * 
 * @author gsh
 * @version 创建时间：2019年5月10日 上午10:13:08
 * 
 */
public class ZipCompress {

	static Logger log = LoggerFactory.getLogger(ZipCompress.class);

	private static ZipOutputStream zipOutStream;
	private OutputStream outputStream;

	public ZipCompress(OutputStream outputStream) {
		super();
		this.outputStream = outputStream;
		// -- 包装成ZIP格式输出流
		zipOutStream = new ZipOutputStream(new BufferedOutputStream(outputStream));
		// -- 设置压缩方法
		zipOutStream.setMethod(ZipOutputStream.DEFLATED);
	}

	/**
	 * 根据路径压缩文件， 目前只支持文件，不支持文件夹
	 * 
	 * @Title: compressByPaths
	 * @Description:
	 * @author：gsh
	 * @date: 2019年5月10日
	 * @param paths 路径
	 * @throws DownLoadException
	 * @return void
	 */
	public void compressByPaths(List<String> paths) throws DownLoadException {
		compressByPaths(paths, null, null);
	}

	/**
	 * 根据路径压缩文件， 目前只支持文件，不支持文件夹
	 * 
	 * @Title: compressByPaths
	 * @Description:
	 * @author：gsh
	 * @date: 2019年5月10日
	 * @param paths  路径
	 * @param folder 目录
	 * @throws DownLoadException
	 * @return void
	 */
	public void compressByPaths(List<String> paths, String folder) throws DownLoadException {
		compressByPaths(paths, null, folder);
	}

	/**
	 * 根据路径压缩文件， 目前只支持文件，不支持文件夹
	 * 
	 * @Title: compressByPaths
	 * @Description:
	 * @author：gsh
	 * @date: 2019年5月10日
	 * @param paths     路径
	 * @param fileNames 文件名
	 * @param folder    目录
	 * @throws DownLoadException
	 * @return void
	 */
	public void compressByPaths(List<String> paths, List<String> fileNames, String folder) throws DownLoadException {
		if (paths == null || paths.size() == 0) {
			throw new DownLoadException("未获取到数据");
		}
		List<File> files = new ArrayList<File>();
		for (String path : paths) {
			files.add(new File(path));
		}
		compressByFiles(files, fileNames, folder);
	}

	/**
	 * 
	 * @Title: compressByFiles
	 * @Description: 压缩文件根据file， 目前只支持文件，不支持文件夹
	 * @author：gsh
	 * @date: 2019年5月10日
	 * @param files 文件
	 * @throws DownLoadException
	 * @return void
	 */
	public void compressByFiles(List<File> files) throws DownLoadException {
		compressByFiles(files, null, null);
	}

	/**
	 * 压缩文件根据file， 目前只支持文件，不支持文件夹
	 * 
	 * @Title: compressByFiles
	 * @Description:
	 * @author：gsh
	 * @date: 2019年5月10日
	 * @param files  文件
	 * @param folder 目录
	 * @throws DownLoadException
	 * @return void
	 */
	public void compressByFiles(List<File> files, String folder) throws DownLoadException {
		compressByFiles(files, null, folder);
	}

	/**
	 * 压缩文件根据file， 目前只支持文件，不支持文件夹
	 * 
	 * @Title: compressByFiles
	 * @Description:
	 * @author：gsh
	 * @date: 2019年5月10日
	 * @param files     文件
	 * @param fileNames 新文件名
	 * @param folder    目录
	 * @throws DownLoadException
	 * @return void
	 */
	public void compressByFiles(List<File> files, List<String> fileNames, String folder) throws DownLoadException {
		if (files == null || files.size() == 0) {
			throw new DownLoadException("未获取到数据");
		}
		boolean isNewFileName = false;// 是否使用传入文件名称
		if (fileNames != null && fileNames.size() == files.size()) {
			isNewFileName = true;
		}
		try {
			// -- 将多文件循环写入压缩包
			if (folder != null && !folder.equals("")) {
				folder = folder + File.separator;
			}
			for (int i = 0; i < files.size(); i++) {
				File file = files.get(i);

				BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
				// -- 添加ZipEntry，并ZipEntry中写入文件流
				if (isNewFileName) {// 使用传入文件名
					zipOutStream.putNextEntry(new ZipEntry(folder + i + "-" + fileNames.get(i)));// i 防止文件名重复
				} else {
					zipOutStream.putNextEntry(new ZipEntry(folder + file.getName()));
				}
				int count;
				byte[] buf = new byte[1024];
				while ((count = bis.read(buf)) != -1) {
					zipOutStream.write(buf, 0, count);
				}

				zipOutStream.closeEntry();
				bis.close();
			}
		} catch (IOException e) {
			log.error(getExceptionAllinformation(e));
			throw new DownLoadException("下载错误");
		}
	}

	/**
	 * 
	 * @Title: flush
	 * @Description: 刷新
	 * @author：gsh
	 * @date: 2019年5月10日
	 * @return void
	 * @throws DownLoadException
	 */
	public void flush() throws DownLoadException {
		try {
			zipOutStream.flush();
		} catch (IOException e) {
			log.error(getExceptionAllinformation(e));
			throw new DownLoadException("下载错误");
		}
	}

	/**
	 * 
	 * @Title: close
	 * @Description: 关闭
	 * @author：gsh
	 * @date: 2019年5月10日
	 * @return void
	 * @throws DownLoadException
	 */
	public void close() throws DownLoadException {
		try {
			if (zipOutStream != null) {
				zipOutStream.close();
			}
//			if (outputStream != null) {
//				outputStream.close();
//			}
		} catch (IOException e) {
			log.error(getExceptionAllinformation(e));
			throw new DownLoadException("下载错误");
		}
	}

	public static String getExceptionAllinformation(Exception ex) {
		String sOut = "\tat " + ex.getMessage() + "\r\n";

		StackTraceElement[] trace = ex.getStackTrace();
		for (StackTraceElement s : trace) {
			sOut += "\tat " + s + "\r\n";
		}
		return sOut;
	}

	public static void compressByFiles1(List<InputStream> ins, OutputStream outputStream, List<String> fileNames,
			String typeName) throws DownLoadException, IOException {

		ZipCompress zc = new ZipCompress(outputStream);
		zc.compressByFiles1(ins, typeName, fileNames);
		zc.close();
	}

	public void compressByFiles1(List<InputStream> ins, String folder, List<String> fileNames)
			throws IOException, DownLoadException {
		if (ins == null || ins.size() == 0) {
			throw new DownLoadException("未获取到数据");
		}
		boolean isNewFileName = false;// 是否使用传入文件名称
		if (fileNames != null && fileNames.size() == ins.size()) {
			isNewFileName = true;
		}
		try {
			// -- 将多文件循环写入压缩包
			if (folder != null && !folder.equals("")) {
				folder = folder + File.separator;
			}
			for (int i = 0; i < ins.size(); i++) {
				InputStream is = ins.get(i);

				BufferedInputStream bis = new BufferedInputStream(is);
				if (isNewFileName) {// 使用传入文件名
					zipOutStream.putNextEntry(new ZipEntry(folder + fileNames.get(i)));// i 防止文件名重复
				} else {
					zipOutStream.putNextEntry(new ZipEntry(folder + i));
				}
				int count;
				byte[] buf = new byte[1024];
				while ((count = bis.read(buf)) != -1) {
					zipOutStream.write(buf, 0, count);
				}

				zipOutStream.closeEntry();
				is.close();
				bis.close();
			}
		} catch (IOException e) {
			log.error(getExceptionAllinformation(e));
			throw new DownLoadException("下载错误");
		}
	}
}
